/*------------------------------------------------------------------------------
 sys_pmu.s

 Copyright (C) 2009-2018 Texas Instruments Incorporated - www.ti.com


  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions
  are met:

    Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.

    Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the
    distribution.

    Neither the name of Texas Instruments Incorporated nor the names of
    its contributors may be used to endorse or promote products derived
    from this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

---------------------------------------------------------------------------*/


    .section .text
    .syntax unified
    .cpu cortex-r4
    .arm

/*-------------------------------------------------------------------------------*/
@ Initialize Pmu
@ Note: It will reset all counters

    .weak _pmuInit_
    .type _pmuInit_, %function

_pmuInit_:

        @ set control register
        mrc   p15, #0, r0, c9, c12, #0
        orr   r0,  r0, #(1 << 4) + 6 + 1
        mcr   p15, #0, r0, c9, c12, #0
        @ clear flags
        mov   r0,  #0
        sub   r0,  r0,  #1
        mcr   p15, #0, r0, c9, c12, #3
        @ select counter 0 event
		mov   r0,  #0
        mcr   p15, #0, r0, c9, c12, #5 @ select counter
        mov   r0,  #0x11
        mcr   p15, #0, r0, c9, c13, #1 @ select event
        @ select counter 1 event
        mov   r0,  #1
        mcr   p15, #0, r0, c9, c12, #5 @ select counter
        mov   r0,  #0x11
        mcr   p15, #0, r0, c9, c13, #1 @ select event
        @ select counter 2 event
        mov   r0,  #2
        mcr   p15, #0, r0, c9, c12, #5 @ select counter
        mov   r0,  #0x11
        mcr   p15, #0, r0, c9, c13, #1 @ select event
        bx    lr

/*-------------------------------------------------------------------------------*/
@ Enable Counters Global [Cycle, Event [0..2]]
@ Note: It will reset all counters

    .weak     _pmuEnableCountersGlobal_
    .type     _pmuEnableCountersGlobal_, %function

_pmuEnableCountersGlobal_:

        mrc   p15, #0, r0, c9, c12, #0
        orr   r0,  r0, #7
        mcr   p15, #0, r0, c9, c12, #0
        bx    lr

/*-------------------------------------------------------------------------------*/
@ Disable Counters Global [Cycle, Event [0..2]]

    .weak     _pmuDisableCountersGlobal_
    .type     _pmuDisableCountersGlobal_, %function

_pmuDisableCountersGlobal_:

        mrc   p15, #0, r0, c9, c12, #0
        bic   r0,  r0, #1
        mcr   p15, #0, r0, c9, c12, #0
        bx    lr

/*-------------------------------------------------------------------------------*/
@ Reset Cycle Counter

    .weak     _pmuResetCycleCounter_
    .type     _pmuResetCycleCounter_, %function

_pmuResetCycleCounter_:

        mrc   p15, #0, r0, c9, c12, #0
        orr   r0,  r0, #4
        mcr   p15, #0, r0, c9, c12, #0
        bx    lr

/*-------------------------------------------------------------------------------*/
@ Reset Event Counters [0..2]

    .weak     _pmuResetEventCounters_
    .type     _pmuResetEventCounters_, %function

_pmuResetEventCounters_:

        mrc   p15, #0, r0, c9, c12, #0
        orr   r0,  r0, #2
        mcr   p15, #0, r0, c9, c12, #0
        bx    lr

/*-------------------------------------------------------------------------------*/
@ Reset Cycle Counter abd Event Counters [0..2]

    .weak     _pmuResetCounters_
    .type     _pmuResetCounters_, %function

_pmuResetCounters_:

        mrc   p15, #0, r0, c9, c12, #0
        orr   r0,  r0, #6
        mcr   p15, #0, r0, c9, c12, #0
        bx    lr

/*-------------------------------------------------------------------------------*/
@ Start Counters [Cycle, 0..2]

    .weak     _pmuStartCounters_
    .type     _pmuStartCounters_, %function

_pmuStartCounters_:

        mcr   p15, #0, r0, c9, c12, #1
        bx    lr

/*-------------------------------------------------------------------------------*/
@ Stop Counters [Cycle, 0..2]

    .weak     _pmuStopCounters_
    .type     _pmuStopCounters_, %function

_pmuStopCounters_:

        mcr   p15, #0, r0, c9, c12, #2
        bx    lr

/*-------------------------------------------------------------------------------*/
@ Set Count event

    .weak     _pmuSetCountEvent_
    .type     _pmuSetCountEvent_, %function

_pmuSetCountEvent_:

        mcr   p15, #0, r0, c9, c12, #5 @ select counter
        mcr   p15, #0, r1, c9, c13, #1 @ select event
        bx    lr

/*-------------------------------------------------------------------------------*/
@ Get Cycle Count

    .weak     _pmuGetCycleCount_
    .type     _pmuGetCycleCount_, %function

_pmuGetCycleCount_:

        mrc   p15, #0, r0, c9, c13, #0
        bx    lr

/*-------------------------------------------------------------------------------*/
@ Get Event Counter Count Value

    .weak     _pmuGetEventCount_
    .type     _pmuGetEventCount_, %function

_pmuGetEventCount_:

        mcr   p15, #0, r0, c9, c12, #5 @ select counter
        mrc   p15, #0, r0, c9, c13, #2 @ read event counter
        bx    lr

/*-------------------------------------------------------------------------------*/
@ Get Overflow Flags

    .weak     _pmuGetOverflow_
    .type     _pmuGetOverflow_, %function

_pmuGetOverflow_:

        mrc   p15, #0, r0, c9, c12, #3 @ read overflow
        mov   r1,  #0
        sub   r1,  r1,  #1
        mcr   p15, #0, r1, c9, c12, #3 @ clear flags
        bx    lr

/*-------------------------------------------------------------------------------*/

